<?php namespace sacvoyage\storage;


require_once 'sacvoyage/storage/Selector.php';
use sacvoyage\storage\Selector;

require_once("sacvoyage/Pathfinder.php"); 
use \sacvoyage\Pathfinder;




class Reducer implements \Iterator {

	private $_result=array();

	public function __construct($table, $keyIterator, $aggregate) {
		$this->_table=$table;
		$this->_keyIterator=$keyIterator;
		$this->_aggregate=$aggregate;

		$selector=new Selector($table, $keyIterator, $aggregate);
		foreach($selector as $document) {
			$this->_watch($document);
		}
	}

	public function rewind() {
		return reset($this->_result);
	}

	public function key() {
		return key($this->_result);
	}

	public function current() {
		return current($this->_result);
	}
	
	public function next() {
		next($this->_result);
	}

	public function valid() {
		return current($this->_result)!==false;
	}
	
	private $_table;
	private $_keyIterator;
	private $_aggregate;
		
	private function _reset() {
		$this->_result=array();
	}
	
	private function _watch($newDocument) {
		$aggregatePathfinder=new Pathfinder($this->_aggregate);
		$newDocumentPathfinder=new PathFinder($newDocument);

		foreach($this->_result as &$document) {
			$pathfinder=new Pathfinder($document);
			
			foreach($aggregatePathfinder->get() as $path=>$value) {
				// if some field does not match ...
				if($value=='_group' 
				&& $newDocumentPathfinder[$path]!=$pathfinder[$path]){ 
					continue 2;
				}
			}
			
			// we've found
			foreach($aggregatePathfinder->get() as $path=>$aggregationType) {
				if($aggregationType=='_group') {
					continue;
				}
				if(!in_array($aggregationType, array('_count','_sum', '_min', '_max'))) {
					throw new \Exception("$aggregationType-aggregation is not supported");
				}
				if(!isset($newDocumentPathfinder[$path])) {
					continue;
				}
				
				if(isset($pathfinder[$path])) {
					if		($aggregationType=='_count') {
						$pathfinder[$path]=$pathfinder[$path]+1;
					} elseif($aggregationType=='_sum') {
						$pathfinder[$path]=$pathfinder[$path]+$newDocumentPathfinder[$path];
					} elseif($aggregationType=='_min') {
					 	$pathfinder[$path]=min($pathfinder[$path], $newDocumentPathfinder[$path]);
					} elseif($aggregationType=='_max') {
						$pathfinder[$path]=max($pathfinder[$path], $newDocumentPathfinder[$path]);
					} else {
						assert(false);
					}
				} else {
					if($aggregationType=='_count') {
						$pathfinder[$path]=1;
					} else {
						$pathfinder[$path]=$newDocumentPathfinder[$path];
					}
				}
				
			} 
			
			return;
		}
		
		foreach($aggregatePathfinder->get() as $path=>$aggregationType) {
			if($aggregationType=='_group') {
				continue;
			}
			if(!in_array($aggregationType, array('_count','_sum', '_min', '_max'))) {
				throw new \Exception("$aggregationType-aggregation is not supported");
			}
			if($aggregationType=='_count' 
			&& isset($newDocumentPathfinder[$path])) {
				$newDocumentPathfinder[$path]=1;
			}
		}
		
		$this->_result[]=$newDocument;
	}
			

	
}


?>
